package org.dromara.platform.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import me.chanjar.weixin.open.bean.result.WxOpenResult;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.platform.domain.TMiniProgramBaseInfo;
import org.dromara.platform.domain.bo.BatchTMiniProgramCategoryBo;
import org.dromara.platform.domain.vo.MiniProgramCategorySelectVo;
import org.dromara.platform.mapper.TMiniProgramBaseInfoMapper;
import org.dromara.wechat.domain.CategoryBo;
import org.dromara.wechat.domain.vo.CategoryVo;
import org.dromara.wechat.domain.vo.ConfiguredCategoriesVo;
import org.dromara.wechat.domain.vo.ConfiguredCategoryVo;
import org.dromara.wechat.domain.vo.WechatCategoryVo;
import org.dromara.wechat.enums.WechatEnums;
import org.dromara.wechat.service.WechatOpenService;
import org.springframework.stereotype.Service;
import org.dromara.platform.domain.bo.TMiniProgramCategoryBo;
import org.dromara.platform.domain.vo.TMiniProgramCategoryVo;
import org.dromara.platform.domain.TMiniProgramCategory;
import org.dromara.platform.mapper.TMiniProgramCategoryMapper;
import org.dromara.platform.service.ITMiniProgramCategoryService;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Collection;

import static org.dromara.wechat.constants.WechatConstants.SUCCESS;

/**
 * 小程序类目信息Service业务层处理
 *
 * @author Lion Li
 * @date 2025-06-11
 */
@RequiredArgsConstructor
@Service
public class TMiniProgramCategoryServiceImpl implements ITMiniProgramCategoryService {

    private final TMiniProgramCategoryMapper baseMapper;
    private final WechatOpenService wechatOpenService;
    private final TMiniProgramBaseInfoMapper miniProgramBaseInfoMapper;

    /**
     * 查询小程序类目信息
     *
     * @param id 主键
     * @return 小程序类目信息
     */
    @Override
    public TMiniProgramCategoryVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询小程序类目信息列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 小程序类目信息分页列表
     */
    @Override
    public TableDataInfo<TMiniProgramCategoryVo> queryPageList(TMiniProgramCategoryBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<TMiniProgramCategory> lqw = buildQueryWrapper(bo);
        Page<TMiniProgramCategoryVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的小程序类目信息列表
     *
     * @param bo 查询条件
     * @return 小程序类目信息列表
     */
    @Override
    public List<TMiniProgramCategoryVo> queryList(TMiniProgramCategoryBo bo) {
        LambdaQueryWrapper<TMiniProgramCategory> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<TMiniProgramCategory> buildQueryWrapper(TMiniProgramCategoryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<TMiniProgramCategory> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(TMiniProgramCategory::getId);
        lqw.eq(bo.getBaseId() != null, TMiniProgramCategory::getBaseId, bo.getBaseId());
        lqw.eq(bo.getCategoryId() != null, TMiniProgramCategory::getCategoryId, bo.getCategoryId());
        lqw.eq(StringUtils.isNotBlank(bo.getCategoryClass()), TMiniProgramCategory::getCategoryClass, bo.getCategoryClass());
        lqw.eq(bo.getParentCategoryId() != null, TMiniProgramCategory::getParentCategoryId, bo.getParentCategoryId());
        lqw.eq(StringUtils.isNotBlank(bo.getParentCategoryClass()), TMiniProgramCategory::getParentCategoryClass, bo.getParentCategoryClass());
        lqw.eq(StringUtils.isNotBlank(bo.getLevel()), TMiniProgramCategory::getLevel, bo.getLevel());
        lqw.eq(bo.getStatus() != null, TMiniProgramCategory::getStatus, bo.getStatus());
        return lqw;
    }

    /**
     * 新增小程序类目信息
     *
     * @param bo 小程序类目信息
     * @return 是否新增成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(TMiniProgramCategoryBo bo) {
        TMiniProgramCategory add = MapstructUtils.convert(bo, TMiniProgramCategory.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改小程序类目信息
     *
     * @param bo 小程序类目信息
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(TMiniProgramCategoryBo bo) {
        TMiniProgramCategory update = MapstructUtils.convert(bo, TMiniProgramCategory.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(TMiniProgramCategory entity){
        //TODO 做一些数据校验,如唯一约束
        // 修改时查询是否存在相同的类目
//        LambdaQueryWrapper<TMiniProgramCategory> lqw = Wrappers.lambdaQuery();
//        lqw.eq(TMiniProgramCategory::getBaseId, entity.getBaseId());
//        lqw.eq(TMiniProgramCategory::getCategoryId, entity.getCategoryId());
//        TMiniProgramCategory tMiniProgramCategory = baseMapper.selectOne(lqw);
//        if (null != tMiniProgramCategory && !tMiniProgramCategory.getId().equals(entity.getId())) {
//            throw new ServiceException("类目已存在");
//        }
    }

    /**
     * 校验并批量删除小程序类目信息信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }


    @Override
    public List<MiniProgramCategorySelectVo> wxCategorySelect(Long baseId) {
        List<MiniProgramCategorySelectVo> result = new ArrayList<>();
        TMiniProgramBaseInfo baseInfo = miniProgramBaseInfoMapper.selectById(baseId);
        if (null == baseInfo) {
            throw new ServiceException("小程序不存在");
        }
        WechatCategoryVo wechatCategoryVo = wechatOpenService.getAllCategoriesByType(baseInfo.getAppid());
        // 分类列表
        // 获取一级分类
        List<CategoryVo> oneLevelCategories = wechatCategoryVo.getCategories().stream().filter(category -> null != category.getLevel() && category.getLevel() == 1).toList();
        oneLevelCategories.forEach(oneLevelCategory -> {
            MiniProgramCategorySelectVo miniProgramCategorySelectVo = new MiniProgramCategorySelectVo();
            miniProgramCategorySelectVo.setCategoryId(oneLevelCategory.getId());
            miniProgramCategorySelectVo.setCategoryName(oneLevelCategory.getName());
            miniProgramCategorySelectVo.setCategoryLevel(oneLevelCategory.getLevel());
            miniProgramCategorySelectVo.setSensitiveType(oneLevelCategory.getSensitive_type());
            miniProgramCategorySelectVo.setQualify(oneLevelCategory.getQualify());
            result.add(miniProgramCategorySelectVo);
        });
        // 获取二级分类
        List<CategoryVo> twoLevelCategories = wechatCategoryVo.getCategories().stream().filter(category -> null != category.getLevel() && category.getLevel() == 2).toList();
        result.stream().forEach(parentCategory -> {
            List<MiniProgramCategorySelectVo> childCategoryList = new ArrayList<>();
            List<CategoryVo> childCategory = twoLevelCategories.stream().filter(category -> category.getFather() == parentCategory.getCategoryId()).toList();
            childCategory.forEach(child -> {
                MiniProgramCategorySelectVo childCategorySelectVo = new MiniProgramCategorySelectVo();
                childCategorySelectVo.setCategoryId(child.getId());
                childCategorySelectVo.setCategoryName(child.getName());
                childCategorySelectVo.setCategoryLevel(child.getLevel());
                childCategorySelectVo.setParentCategoryId(parentCategory.getCategoryId());
                childCategorySelectVo.setParentCategoryName(parentCategory.getCategoryName());
                childCategorySelectVo.setSensitiveType(child.getSensitive_type());
                childCategorySelectVo.setQualify(child.getQualify());
                childCategoryList.add(childCategorySelectVo);
            });
            parentCategory.setChildren(childCategoryList);
        });
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R batchUpdateCategory(BatchTMiniProgramCategoryBo batchTMiniProgramCategoryBo) {
        StringBuilder result = new StringBuilder();
        try {
            List<TMiniProgramCategoryBo> boList = batchTMiniProgramCategoryBo.getBoList();
            if (CollectionUtils.isEmpty(boList) || null == batchTMiniProgramCategoryBo.getBaseId()) {
                throw new ServiceException("参数不能为空");
            }
            // 获取小程序appid
            TMiniProgramBaseInfo baseInfo = miniProgramBaseInfoMapper.selectById(batchTMiniProgramCategoryBo.getBaseId());
            if (null == baseInfo) {
                throw new ServiceException("小程序不存在");
            }
            // 获取已设置的微信类目
            ConfiguredCategoriesVo wechatCategoryVo = wechatOpenService.getAllCategories(baseInfo.getAppid());
            // 微信已设置的类目id集合
            List<Integer> wechatCategoryIdList = wechatCategoryVo.getCategories().stream().map(ConfiguredCategoryVo::getSecond).toList();
            // 查询已存在的类目
            List<TMiniProgramCategory> existList = baseMapper.selectList(Wrappers.<TMiniProgramCategory>lambdaQuery().in(TMiniProgramCategory::getBaseId, batchTMiniProgramCategoryBo.getBaseId()));
            // 本地已存在的类目id集合
            List<Integer> existIdList = existList.stream().map(TMiniProgramCategory::getCategoryId).toList();
            // 在微信已设置的类目id集合中，但不在本地已存在的类目id集合中，则为待删除的类目
            List<Integer> deleteIdList = wechatCategoryIdList.stream().filter(id -> !existIdList.contains(id)).toList();
            // 待删除的类目集合
            List<TMiniProgramCategory> deleteList = existList.stream().filter(category -> deleteIdList.contains(category.getCategoryId())).toList();
            // 删除类目
            batchDeleteCategory(deleteList, baseInfo.getAppid(), result);

            // 同时不在微信已设置的类目id集合、本地已存在的类目id集合中，则为待新增的类目
            // 待新增的类目集合
            List<TMiniProgramCategoryBo> insertBoList = boList.stream().filter(bo -> !existIdList.contains(bo.getCategoryId()) && !wechatCategoryIdList.contains(bo.getCategoryId())).toList();
            // 新增类目
            batchInsertCategory(insertBoList, baseInfo.getAppid(), result);
            // 同时在微信已设置的类目id集合、本地已存在的类目id集合中，且内容不一致，则为待更新的类目
            // 待更新的类目集合 todo
//            List<TMiniProgramCategoryBo> updateBoList = boList.stream().filter(bo -> existIdList.contains(bo.getCategoryId()) && wechatCategoryIdList.contains(bo.getCategoryId())
//                && !existList.stream().anyMatch(category -> category.getCategoryId().equals(bo.getCategoryId()) && !category.getCategoryClass().equals(bo.getCategoryClass()))).toList();
//            // 更新类目
//            updateBoList.stream().forEach(bo -> {
//                updateByBo(bo);
//            });
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
        if (result.length() > 0) {
            R.fail(result.toString());
        }
        return R.ok();
    }

    private void batchDeleteCategory(List<TMiniProgramCategory> deleteList, String appid, StringBuilder result) {
        // 调用微信删除类目接口
        deleteList.stream().forEach(bo -> {
            CategoryBo categoryBo = new CategoryBo();
            categoryBo.setFirst(bo.getParentCategoryId());
            categoryBo.setSecond(bo.getCategoryId());
            WxOpenResult wxOpenResult = wechatOpenService.deleteCategory(appid, categoryBo);
            if (null != wxOpenResult && !WechatEnums.SUCCESS.equals( wxOpenResult.getErrcode())) {
                result.append("删除类目{" + bo.getCategoryClass() + "}失败：" + wxOpenResult.getErrmsg() + "，");
            }else{
                baseMapper.deleteByBaseIdAndCategoryId(bo.getBaseId(), bo.getCategoryId());
            }
        });
    }

    private void batchInsertCategory(List<TMiniProgramCategoryBo> insertBoList, String appid, StringBuilder result) {
        // 调用微信配置类目接口
        insertBoList.stream().forEach(bo -> {
            CategoryBo categoryBo = new CategoryBo();
            categoryBo.setFirst(bo.getParentCategoryId());
            categoryBo.setSecond(bo.getCategoryId());
            categoryBo.setCerticates(bo.getCerticates());
            WxOpenResult wxOpenResult = wechatOpenService.addCategory(appid, categoryBo);
            if (null != wxOpenResult && !WechatEnums.SUCCESS.equals( wxOpenResult.getErrcode())) {
                result.append("新增类目{" + bo.getCategoryClass() + "}失败：" + wxOpenResult.getErrmsg() + "，");
            }else{
                TMiniProgramCategory tMiniProgramCategory = MapstructUtils.convert(bo, TMiniProgramCategory.class);
                baseMapper.insert(tMiniProgramCategory);
            }
        });

    }
}
